其他
性能优化技巧:TopN
select * from (select * from T order by x desc) where rownum<=N
这个SQL的运算逻辑从其语句上看,要先做排序(Order by),然后再取出前N条。
1. Oracle测试
select * from (
select /*+ parallel(4) */
* from topn order by amount desc
) where rownum<=100;
2. SPL测试
A | ||
1 | =now() | /记录时间 |
2 | =4 | /并行数 |
3 | =file("/home/topn/topn.ctx").open() | /产生组表对象 |
4 | =A3.cursor@m(id,amount;;A2).groups(;top(100;-amount)) | |
5 | =interval@s(A1,now()) | /算出执行时间 |
3. 结论与分析
并行数 | 1 | 2 | 4 | 8 | 12 |
Oracle | 1922 | 952 | 526 | 308 | 256 |
SPL组表 | 2641 | 1565 | 729 | 371 | 321 |
1. Oracle测试
select * from (
select /*+ parallel(2) */
mod(id,10) as gid,amount,
row_number()over (partition by mod(id,10) order by amount desc) rn
from topn
) where rn <= 100;
SQL无法直接写出分组后取TopN的运算,只能借助窗口函数计算序号,语法中还是有排序(order by)的字样。
2. SPL组表测试
A | ||
1 | =now() | /记录时间 |
2 | =4 | /并行数 |
3 | =file("/home/topn/topn.ctx").open() | /产生组表对象 |
4 | =A3.cursor@m(id,amount;;A2).groups@u(id%10:gid;top(100;-amount)) | |
5 | =interval@s(A1,now()) | /算出执行时间 |
因为SPL把TopN看成是聚合计算,所以可以很容易放在分组汇总中,和全量聚合的写法几乎是一样的。
并行数 | 1 | 2 | 4 | 8 | 12 |
Oracle | 41649 | 19602 | 9359 | 4627 | 3211 |
SPL组表 | 4380 | 2127 | 1007 | 465 | 349 |
增加难度后,Oracle比之前的简单情况慢了10倍还多,而且比SPL做同样运算也慢了近10倍。这说明Oracle在这种情况下很可能做了排序动作,情况复杂化之后,Oracle的优化引擎不起作用了。
更多性能优化技巧,可在底部“阅读原文”中查看
重磅!开源SPL交流群成立了
简单好用的SPL开源啦!
为了给感兴趣的小伙伴们提供一个相互交流的平台,
特地开通了交流群(群完全免费,不广告不卖课)
需要进群的朋友,可长按扫描下方二维码
本文感兴趣的朋友,请转到阅读原文去收藏 ^_^